home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / Apps / ArchiveUtils / nx_arc / arcunp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-20  |  5.5 KB  |  223 lines

  1. /*
  2.  * $Log:    arcunp.c,v $
  3.  * Revision 1.1  88/04/11  18:42:39  hyc
  4.  * Initial revision
  5.  * 
  6.  * Revision 1.3  87/12/20  03:10:14  hyc
  7.  * Ah hah! The value fgetc was returning was getting sign extended!
  8.  * Thus, 0xff was indistinguishable from EOF, causing the premature
  9.  * termination... The solution is to use getc, which doesn't do this
  10.  * (on the Apollos, anyway...)
  11.  * 
  12.  * Note that I could *not* duplicate this behavior in a 5 liner...?
  13.  * 
  14.  * Revision 1.2  87/12/19  04:11:22  hyc
  15.  * Move image mode code around from MTS only to non-MSDOS.
  16.  * 
  17.  * Revision 1.1  87/12/19  04:06:39  hyc
  18.  * Initial revision
  19.  * 
  20.  * Revision 1.3  87/08/13  17:06:08  hyc
  21.  * Run thru indent, fixed some signed vs. unsigned problems
  22.  * with bp <-> buf, and inbuf and localbuf...
  23.  *  Revision 1.2  87/07/21  09:28:31  hyc *** empty
  24.  * log message ***
  25.  * 
  26.  */
  27.  
  28. /*
  29.  * ARC - Archive utility - ARCUNP
  30.  * 
  31.  * Version 3.17, created on 02/13/86 at 10:20:08
  32.  * 
  33.  * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  34.  * 
  35.  * By:  Thom Henderson
  36.  * 
  37.  * Description: This file contains the routines used to expand a file when
  38.  * taking it out of an archive.
  39.  * 
  40.  * Language: Computer Innovations Optimizing C86
  41.  */
  42. #include <stdio.h>
  43. #include "arc.h"
  44.  
  45. /* stuff for repeat unpacking */
  46.  
  47. #define DLE 0x90        /* repeat byte flag */
  48.  
  49. static INT      state;        /* repeat unpacking state */
  50.  
  51. /* repeat unpacking states */
  52.  
  53. #define NOHIST 0        /* no relevant history */
  54. #define INREP 1            /* sending a repeated value */
  55.  
  56. static INT      crcval;        /* CRC check value */
  57. static LONG     size;        /* bytes to read */
  58.  
  59. INT
  60. unpack(f, t, hdr)        /* unpack an archive entry */
  61.     FILE           *f, *t;    /* source, destination */
  62.     struct heads   *hdr;    /* pointer to file header data */
  63. {
  64.     INT             c;    /* one char of stream */
  65.     INT             putc_unp();
  66.     INT             putc_ncr();
  67.     INT             getc_unp();
  68.  
  69.     /* setups common to all methods */
  70.  
  71.     crcval = 0;        /* reset CRC check value */
  72.     size = hdr->size;    /* set input byte counter */
  73.     state = NOHIST;        /* initial repeat unpacking state */
  74.     setcode();        /* set up for decoding */
  75.  
  76.     /* use whatever method is appropriate */
  77.  
  78.     switch (hdrver) {    /* choose proper unpack method */
  79.     case 1:        /* standard packing */
  80.     case 2:
  81.         while ((c = getc_unp(f)) != EOF)
  82.             putc_unp(c, t);
  83.         break;
  84.  
  85.     case 3:        /* non-repeat packing */
  86.         while ((c = getc_unp(f)) != EOF)
  87.             putc_ncr(c, t);
  88.         break;
  89.  
  90.     case 4:        /* Huffman squeezing */
  91.         init_usq(f);
  92.         while ((c = getc_usq(f)) != EOF)
  93.             putc_ncr(c, t);
  94.         break;
  95.  
  96.     case 5:        /* Lempel-Zev compression */
  97.         init_ucr(0);
  98.         while ((c = getc_ucr(f)) != EOF)
  99.             putc_unp(c, t);
  100.         break;
  101.  
  102.     case 6:        /* Lempel-Zev plus non-repeat */
  103.         init_ucr(0);
  104.         while ((c = getc_ucr(f)) != EOF)
  105.             putc_ncr(c, t);
  106.         break;
  107.  
  108.     case 7:        /* L-Z plus ncr with new hash */
  109.         init_ucr(1);
  110.         while ((c = getc_ucr(f)) != EOF)
  111.             putc_ncr(c, t);
  112.         break;
  113.  
  114.     case 8:        /* dynamic Lempel-Zev */
  115.         decomp(f, t);
  116.         break;
  117.  
  118.     case 9:        /* Squashing */
  119.         sqdecomp(f, t);
  120.         break;
  121.  
  122.     default:        /* unknown method */
  123.         if (warn) {
  124.             printf("I don't know how to unpack file %s\n", hdr->name);
  125.             printf("I think you need a newer version of ARC\n");
  126.             nerrs++;
  127.         }
  128.         fseek(f, hdr->size, 1);    /* skip over bad file */
  129.         return 1;    /* note defective file */
  130.     }
  131.  
  132.     /* cleanups common to all methods */
  133.  
  134.     if (crcval != hdr->crc) {
  135.         if (warn || kludge) {
  136.             printf("WARNING: File %s fails CRC check\n", hdr->name);
  137.             nerrs++;
  138.         }
  139.         return 1;    /* note defective file */
  140.     }
  141.     return 0;        /* file is okay */
  142. }
  143.  
  144. /*
  145.  * This routine is used to put bytes in the output file.  It also performs
  146.  * various housekeeping functions, such as maintaining the CRC check value.
  147.  */
  148.  
  149. INT
  150. putc_unp(c, t)            /* output an unpacked byte */
  151.     char            c;    /* byte to output */
  152.     FILE           *t;    /* file to output to */
  153. {
  154.     crcval = addcrc(crcval, c);    /* update the CRC check value */
  155. #ifdef    MTS
  156.     if (!image)
  157.         atoe(&c, 1);
  158. #endif
  159. #ifndef MSDOS
  160.     if ((c != '\r') || image)
  161. #endif
  162.         putc_tst(c, t);
  163. }
  164.  
  165. /*
  166.  * This routine is used to decode non-repeat compression.  Bytes are passed
  167.  * one at a time in coded format, and are written out uncoded. The data is
  168.  * stored normally, except that runs of more than two characters are
  169.  * represented as:
  170.  * 
  171.  * <char> <DLE> <count>
  172.  * 
  173.  * With a special case that a count of zero indicates a DLE as data, not as a
  174.  * repeat marker.
  175.  */
  176.  
  177. INT
  178. putc_ncr(c, t)            /* put NCR coded bytes */
  179.     unsigned char   c;    /* next byte of stream */
  180.     FILE           *t;    /* file to receive data */
  181. {
  182.     static INT      lastc;    /* last character seen */
  183.  
  184.     switch (state) {    /* action depends on our state */
  185.     case NOHIST:        /* no previous history */
  186.         if (c == DLE)    /* if starting a series */
  187.             state = INREP;    /* then remember it next time */
  188.         else
  189.             putc_unp(lastc = c, t);    /* else nothing unusual */
  190.         return;
  191.  
  192.     case INREP:        /* in a repeat */
  193.         if (c)        /* if count is nonzero */
  194.             while (--c)    /* then repeatedly ... */
  195.                 putc_unp(lastc, t);    /* ... output the byte */
  196.         else
  197.             putc_unp(DLE, t);    /* else output DLE as data */
  198.         state = NOHIST;    /* back to no history */
  199.         return;
  200.  
  201.     default:
  202.         arc_abort("Bad NCR unpacking state (%d)", state);
  203.     }
  204. }
  205.  
  206. /*
  207.  * This routine provides low-level byte input from an archive.  This routine
  208.  * MUST be used, as end-of-file is simulated at the end of the archive entry.
  209.  */
  210.  
  211. INT
  212. getc_unp(f)            /* get a byte from an archive */
  213.     FILE           *f;    /* archive file to read */
  214. {
  215.     register INT    xx;
  216.     if (!size)        /* if no data left */
  217.         return EOF;    /* then pretend end of file */
  218.  
  219.     size--;            /* deduct from input counter */
  220.     xx = getc(f);
  221.     return code(xx);    /* and return next decoded byte */
  222. }
  223.